home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 June / MacFormat 25.iso / Shareware City / Developers / Little Smalltalk v3.1.4 / Smalltalk Source / collect.st < prev    next >
Encoding:
Text File  |  1995-01-26  |  14.6 KB  |  620 lines  |  [TEXT/KAHL]

  1. *
  2. * Little Smalltalk, version 3
  3. * Written by Tim Budd, Oregon State University, July 1988
  4. *
  5. * methods for Collection classes
  6. *
  7. * Changes for v3.1 by Julian Barkway. 
  8. *
  9. * v3.1.0    Initial release
  10. * v3.1.1    -
  11. * v3.1.2    Changed class List to use list end marker for increased efficiency when
  12. *            using add:, addAll: or addLast:
  13. * v3.1.3    Changed Array 'grow:' to use new 'become:' message. 
  14. *
  15. *
  16. Class Link Object key value nextLink
  17. Class Collection Magnitude
  18. Class    IndexedCollection Collection
  19. Class       Array IndexedCollection
  20. Class          ByteArray Array
  21. Class             String ByteArray
  22. Class       Dictionary IndexedCollection hashTable
  23. Class    Interval Collection lower upper step
  24. Class    List Collection links listEnd                 "listEnd added for v3.1.2"
  25. Class       Set List
  26. *
  27. Methods Array 'all'
  28.     < coll
  29.         (coll isKindOf: Array)
  30.             ifTrue: [ self with: coll 
  31.                    do: [:x :y | (x = y) ifFalse: 
  32.                           [ ^ x < y ]].
  33.                   ^ self size < coll size ]
  34.             ifFalse: [ ^ super < coll ]
  35. |
  36.     = coll
  37.         (coll isKindOf: Array)
  38.             ifTrue: [ (self size = coll size)
  39.                     ifFalse: [ ^ false ].
  40.                   self with: coll
  41.                     do: [:x :y | (x = y) 
  42.                         ifFalse: [ ^ false ] ]. 
  43.                  ^ true ]
  44.             ifFalse: [ ^ super = coll ]
  45. |
  46.     basicAt: index put: value
  47.         <31 self index value >
  48. |
  49.     at: index put: value
  50.         (self includesKey: index)
  51.             ifTrue: [ self basicAt: index put: value ]
  52.             ifFalse: [ smalltalk error: 
  53.                 'illegal index to at:put: for array' ]
  54. |
  55.     binaryDo: aBlock
  56.         (1 to: self size) do:
  57.             [:i | aBlock value: i value: (self at: i) ]
  58. |
  59.     collect: aBlock        | s newArray |
  60.         s <- self size.
  61.         newArray <- Array new: s.
  62.         (1 to: s) do: [:i | newArray at: i put: 
  63.             (aBlock value: (self at: i))].
  64.         ^ newArray
  65. |
  66.     copyFrom: low to: high    | newArray newlow newhigh |
  67.         newlow <- low max: 1.
  68.         newhigh <- high min: self size.
  69.         newArray <- self class new: (0 max: newhigh - newlow + 1).
  70.         (newlow to: newhigh)
  71.             do: [:i |  newArray at: ((i - newlow) + 1)
  72.                     put: (self at: i) ].
  73.         ^ newArray
  74. |
  75.     deepCopy
  76.         ^ self deepCopyFrom: 1 to: self size
  77. |
  78.     deepCopyFrom: low to: high    | newArray newlow newhigh |
  79.         newlow <- low max: 1.
  80.         newhigh <- high min: self size.
  81.         newArray <- self class new: (0 max: newhigh - newlow + 1).
  82.         (newlow to: newhigh)
  83.             do: [:i |  newArray at: ((i - newlow) + 1)
  84.                     put: (self at: i) copy ].
  85.         ^ newArray
  86. |
  87.     do: aBlock
  88.         (1 to: self size) do:
  89.             [:i | aBlock value: (self at: i) ]
  90. |
  91.     exchange: a and: b    | temp |
  92.         temp <- self at: a.
  93.         self at: a put: (self at: b).
  94.         self at: b put: temp
  95. |
  96.     grow: aValue    | s newArray |
  97.         s <- self size.
  98.         newArray <- Array new: s + 1.
  99.         (1 to: s) do: [:i | newArray at: i put: (self at: i)].
  100.         newArray at: s+1 put: aValue.
  101.         ^ self become: newArray            " Changed by Julian Barkway for v3.1.3 "
  102. |
  103.     includesKey: index
  104.         ^ index between: 1 and: self size
  105. |
  106.     new
  107.         ^ smalltalk error: 'arrays and strings cannot be created using new'
  108. |
  109.     reverseDo: aBlock
  110.         (self size to: 1 by: -1) do:
  111.             [:i | aBlock value: (self at: i) ]
  112. |
  113.     select: aCond    | newList |
  114.         newList <- List new.
  115.         self do: [:i | (aCond value: i) ifTrue: [newList addLast: i]].
  116.         ^ newList asArray
  117. |
  118.     shallowCopy
  119.         ^ self copyFrom: 1 to: self size
  120. |
  121.     size
  122.         ^ self basicSize
  123. |
  124.     with: newElement    | s newArray |
  125.         s <- self size.
  126.         newArray <- Array new: (s + 1).
  127.         (1 to: s) do: [:i | newArray at: i put: (self at: i) ].
  128.         newArray at: s+1 put: newElement.
  129.         ^ newArray
  130. |
  131.     with: coll do: aBlock
  132.         (1 to: (self size min: coll size))
  133.             do: [:i | aBlock value: (self at: i) 
  134.                     value: (coll at: i) ]
  135. |
  136.     with: coll ifAbsent: z do: aBlock    | xsize ysize |
  137.         xsize <- self size.
  138.         ysize <- coll size.
  139.         (1 to: (xsize max: ysize))
  140.             do: [:i | aBlock value:
  141.               (i <= xsize ifTrue: [ self at: i ] ifFalse: [ z ])
  142.               value:
  143.               (i <= ysize ifTrue: [ coll at: i ] ifFalse: [ z ])]
  144. ]
  145. Methods ByteArray 'all'
  146.     asString
  147.         <22 self String>
  148. |
  149.     basicAt: index put: value
  150.         ^ ((value isMemberOf: Integer) and: [value between: 0 and: 255])
  151.             ifTrue: [ <32 self index value > ]
  152.             ifFalse: [ value print. smalltalk error: 
  153.                 'assign illegal value to ByteArray']
  154. |
  155.     basicAt: index
  156.         ^ <26 self index>
  157. |
  158.     size: value
  159.         ^ <22 <59 value> ByteArray>
  160. ]
  161. Methods Collection 'all'
  162.     < coll
  163.         (coll respondsTo: #includes:)
  164.             ifFalse: [ ^ smalltalk error:
  165.                   'collection compared to non collection'].
  166.         self do: [:x | ((self occurrencesOf: x) < 
  167.             (coll occurrencesOf: x))ifFalse: [ ^ false ]].
  168.         coll do: [:x | (self includes: x) ifFalse: [ ^ true ]].
  169.         ^ false
  170. |
  171.     = coll
  172.         self do: [:x | (self occurrencesOf: x) = 
  173.                 (coll occurrencesOf: x) ifFalse: [ ^ false ] ].
  174.         ^ true
  175. |
  176.     asArray        | newArray i |
  177.         newArray <- Array new: self size.
  178.         i <- 0.
  179.         self do: [:x | i <- i + 1. newArray at: i put: x].
  180.         ^ newArray
  181. |
  182.     asByteArray    | newArray i |
  183.         newArray <- ByteArray new size: self size.
  184.         i <- 0.
  185.         self do: [:x | i <- i + 1. newArray at: i put: x].
  186.         ^ newArray
  187. |
  188.     asSet
  189.         ^ Set new addAll: self
  190. |
  191.     asString
  192.         ^ self asByteArray asString
  193. |
  194.     display
  195.         self do: [:x | x print ]
  196. |
  197.     includes: value
  198.         self do: [:x | (x = value) ifTrue: [ ^ true ] ].
  199.         ^ false
  200. |
  201.     inject: thisValue into: binaryBlock     | last |
  202.         last <- thisValue.
  203.         self do: [:x | last <- binaryBlock value: last value: x].
  204.         ^ last
  205. |
  206.     isEmpty 
  207.         ^ self size == 0
  208. |
  209.     occurrencesOf: anObject
  210.         ^ self inject: 0
  211.                into: [:x :y | (y = anObject) 
  212.                      ifTrue: [x + 1]
  213.                      ifFalse: [x] ]
  214. |
  215.     printString
  216.         ^ ( self inject: self class printString , ' ('
  217.              into: [:x :y | x , ' ' , y printString]), ' )'
  218. |
  219.     size
  220.         ^ self inject: 0 into: [:x :y | x + 1]
  221. |
  222.     sort: aBlock
  223.         ^ self inject: List new
  224.             into: [:x :y | x add: y ordered: aBlock. x]
  225. |
  226.     sort
  227.         ^ self sort: [:x :y | x < y ]
  228. ]
  229. Methods Dictionary 'all'
  230.     new
  231.         hashTable <- Array new: 39
  232. |
  233.     hash: aKey
  234.         ^ 3 * ((aKey hash) rem: ((hashTable size) quo: 3))
  235. |
  236.     at: aKey ifAbsent: exceptionBlock    | hashPosition  link |
  237.  
  238.         hashPosition <- self hash: aKey.
  239.         ((hashTable at: hashPosition + 1) = aKey)
  240.             ifTrue: [ ^ hashTable at: hashPosition + 2].
  241.         link <- hashTable at: hashPosition + 3.
  242.         ^ (link notNil)
  243.             ifTrue: [ link at: aKey ifAbsent: exceptionBlock ]
  244.             ifFalse: exceptionBlock
  245. |
  246.     at: aKey put: aValue            | hashPosition link |
  247.  
  248.         hashPosition <- self hash: aKey.
  249.         ((hashTable at: hashPosition + 1) isNil)
  250.            ifTrue: [ hashTable at: hashPosition + 1 put: aKey ].
  251.         ((hashTable at: hashPosition + 1) = aKey)
  252.            ifTrue: [ hashTable at: hashPosition + 2 put: aValue ]
  253.            ifFalse: [ link <- hashTable at: hashPosition + 3.
  254.             (link notNil)
  255.                 ifTrue: [ link at: aKey put: aValue ]
  256.                 ifFalse: [ hashTable at: hashPosition + 3
  257.                     put: (Link new; key: aKey; value: aValue)]]
  258. |
  259.     binaryDo: aBlock
  260.         (1 to: hashTable size by: 3) do:
  261.             [:i | (hashTable at: i) notNil
  262.                 ifTrue: [ aBlock value: (hashTable at: i)
  263.                         value: (hashTable at: i+1) ].
  264.                   (hashTable at: i+2) notNil
  265.                 ifTrue: [ (hashTable at: i+2) 
  266.                         binaryDo: aBlock ] ]
  267. |
  268.     display
  269.         self binaryDo: [:x :y | (x printString , ' -> ', 
  270.                     y printString ) print ]
  271. |
  272.     includesKey: aKey
  273.         " look up, but throw away result "
  274.         self at: aKey ifAbsent: [ ^ false ].
  275.         ^ true
  276. |
  277.     removeKey: aKey
  278.         ^ self removeKey: aKey
  279.             ifAbsent: [ smalltalk error: 'remove key not found']
  280. |
  281.     removeKey: aKey ifAbsent: exceptionBlock
  282.         ^ (self includesKey: aKey)
  283.             ifTrue: [ self basicRemoveKey: aKey ]
  284.             ifFalse: exceptionBlock
  285. |
  286.     basicRemoveKey: aKey        | hashPosition link |
  287.         hashPosition <- self hash: aKey.
  288.         ((hashTable at: hashPosition + 1) = aKey)
  289.             ifTrue: [ hashTable at: hashPosition + 1 put: nil.
  290.                   hashTable at: hashPosition + 2 put: nil]
  291.             ifFalse: [ link <- hashTable at: hashPosition + 3.
  292.                 (link notNil)
  293.                     ifTrue: [ hashTable at: hashPosition + 3
  294.                             put: (link removeKey: aKey) ]]
  295. ]
  296. Methods IndexedCollection 'all'
  297.     addAll: aCollection
  298.         aCollection binaryDo: [:i :x | self at: i put: x ]
  299. |
  300.     asArray    
  301.         ^ Array new: self size ; addAll: self
  302. |
  303.     asDictionary
  304.         ^ Dictionary new ; addAll: self
  305. |
  306.     at: aKey
  307.         ^ self at: aKey 
  308.             ifAbsent: [ smalltalk error: 'index to at: illegal']
  309. |
  310.     at: index ifAbsent: exceptionBlock
  311.          ^ (self includesKey: index)
  312.             ifTrue: [ self basicAt: index ]
  313.             ifFalse: exceptionBlock
  314. |
  315.     binaryInject: thisValue into: aBlock     | last |
  316.         last <- thisValue.
  317.         self binaryDo: [:i :x | last <- aBlock value: last 
  318.                         value: i value: x].
  319.         ^ last
  320. |
  321.     collect: aBlock
  322.         ^ self binaryInject: Dictionary new
  323.             into: [:s :i :x | s at: i put: (aBlock value: x).  s]
  324. |
  325.     do: aBlock
  326.         self binaryDo: [:i :x | aBlock value: x ]
  327. |
  328.     keys
  329.         ^ self binaryInject: Set new 
  330.             into: [:s :i :x | s add: i ]
  331. |
  332.     indexOf: aBlock
  333.         ^ self indexOf: aBlock
  334.             ifAbsent: [ smalltalk error: 'index not found']
  335. |
  336.     indexOf: aBlock ifAbsent: exceptionBlock
  337.         self binaryDo: [:i :x | (aBlock value: x)
  338.                 ifTrue: [ ^ i ] ].
  339.         ^ exceptionBlock value
  340. |
  341.     select: aBlock
  342.         ^ self binaryInject: Dictionary new
  343.             into: [:s :i :x | (aBlock value: x)
  344.                     ifTrue: [ s at: i put: x ]. s ]
  345. |
  346.     values
  347.         ^ self binaryInject: List new
  348.             into: [:s :i :x | s add: x ]
  349. ]
  350. Methods Interval 'all'
  351.     do: aBlock        | current |
  352.         current <- lower.
  353.         (step > 0) 
  354.             ifTrue: [ [ current <= upper ] whileTrue:
  355.                     [ aBlock value: current.
  356.                       current <- current + step ] ]
  357.             ifFalse: [ [ current >= upper ] whileTrue:
  358.                     [ aBlock value: current.
  359.                     current <- current + step ] ]
  360. |
  361.     lower: aValue
  362.         lower <- aValue
  363. |
  364.     upper: aValue
  365.         upper <- aValue
  366. |
  367.     step: aValue
  368.         step <- aValue
  369. ]
  370. Methods Link 'all'
  371.     add: newValue whenFalse: aBlock
  372.         (aBlock value: value value: newValue)
  373.             ifTrue: [ (nextLink notNil)
  374.                 ifTrue: [ nextLink <- nextLink add: newValue 
  375.                     whenFalse: aBlock ]
  376.             ifFalse: [ nextLink <- Link new; value: newValue] ]
  377.             ifFalse: [ ^ Link new; value: newValue; link: self ]
  378. |
  379.     at: aKey ifAbsent: exceptionBlock
  380.         (aKey = key)
  381.             ifTrue: [ ^value ]
  382.             ifFalse: [ ^ (nextLink notNil)
  383.                     ifTrue: [ nextLink at: aKey
  384.                             ifAbsent: exceptionBlock ]
  385.                     ifFalse: exceptionBlock ]
  386. |
  387.     at: aKey put: aValue
  388.         (aKey = key)
  389.             ifTrue: [ value <- aValue ]
  390.             ifFalse: [ (nextLink notNil)
  391.                 ifTrue: [ nextLink at: aKey put: aValue]
  392.                 ifFalse: [ nextLink <- Link new;
  393.                         key: aKey; value: aValue] ]
  394. |
  395.     binaryDo: aBlock
  396.         aBlock value: key value: value.
  397.         (nextLink notNil)
  398.             ifTrue: [ nextLink binaryDo: aBlock ]
  399. |
  400.     key: aKey
  401.         key <- aKey
  402. |
  403.     includesKey: aKey
  404.         (key = aKey)
  405.             ifTrue: [ ^ true ].
  406.         (nextLink notNil)
  407.             ifTrue: [ ^ nextLink includesKey: aKey ]
  408.             ifFalse: [ ^ false ]
  409. |
  410.     link: aLink
  411.         nextLink <- aLink
  412. |
  413.     next
  414.         ^ nextLink
  415. |
  416.     removeKey: aKey
  417.         (aKey = key)
  418.             ifTrue: [ ^ nextLink ]
  419.             ifFalse: [ (nextLink notNil)
  420.                 ifTrue: [ nextLink <- nextLink removeKey: aKey]]
  421. |
  422.     removeValue: aValue
  423.         (aValue = value)
  424.             ifTrue: [ ^ nextLink ]
  425.             ifFalse: [ (nextLink notNil)
  426.                 ifTrue: [ nextLink <- nextLink removeValue: aValue]]
  427. |
  428.     reverseDo: aBlock
  429.         (nextLink notNil)
  430.             ifTrue: [ nextLink reverseDo: aBlock ].
  431.         aBlock value: value
  432. |
  433.     size
  434.         (nextLink notNil)
  435.             ifTrue: [ ^ 1 + nextLink size]
  436.             ifFalse: [ ^ 1 ]
  437. |
  438.     value: aValue
  439.         value <- aValue
  440. |
  441.     value
  442.         ^ value
  443. ]
  444. Methods List 'all'
  445.     add: aValue
  446.         ^ self addLast: aValue
  447. |
  448.     add: aValue ordered: aBlock
  449.         (links isNil)
  450.             ifTrue: [ self addFirst: aValue]
  451.             ifFalse: [ links <- links add: aValue 
  452.                     whenFalse: aBlock ]
  453. |
  454.     addAll: aValue
  455.         aValue do: [:x | self add: x ]
  456. |
  457.     addFirst: aValue                "Changed for v3.1.2"
  458.         (links notNil) ifTrue: [
  459.             links <- Link new; value: aValue; link: links
  460.         ]
  461.         ifFalse: [
  462.             links   <- Link new; value: aValue; link: links.
  463.             listEnd <- links
  464.         ]
  465. |
  466.     addLast: aValue                    "Changed for v3.1.2"
  467.         (links isNil)
  468.             ifTrue: [ self addFirst: aValue ]
  469.             ifFalse: [
  470.                 listEnd link: (Link new; value: aValue).
  471.                 listEnd <- listEnd next 
  472.             ]
  473. |
  474.     collect: aBlock
  475.         ^ self inject: self class new
  476.                into: [:x :y | x add: (aBlock value: y). x ]
  477. |
  478.     links
  479.         ^ links  "used to walk two lists in parallel "
  480. |
  481.     reject: aBlock          
  482.         ^ self select: [:x | (aBlock value: x) not ]
  483. |
  484.     reverseDo: aBlock
  485.         (links notNil)
  486.             ifTrue: [ links reverseDo: aBlock ]
  487. |
  488.     select: aBlock          
  489.         ^ self inject: self class new
  490.                into: [:x :y | (aBlock value: y) 
  491.                     ifTrue: [x add: y]. x]
  492. |
  493.     do: aBlock
  494.         (links notNil)
  495.             ifTrue: [ links binaryDo: [:x :y | aBlock value: y]]
  496. |
  497.     first
  498.         ^ (links notNil)
  499.             ifTrue: links
  500.             ifFalse: [ smalltalk error: 'first on empty list']
  501. |
  502.     last                            "Added for v3.1.2"
  503.         ^ (links notNil)
  504.             ifTrue:  listEnd
  505.             ifFalse: [ smalltalk error: 'last on empty list']
  506. |
  507.     removeFirst
  508.         self remove: self first
  509. |
  510.     remove: value    | l |                "Changed for v3.1.2"
  511.         (links notNil)
  512.             ifTrue: [ links <- links removeValue: value ].
  513.         " Tracking listEnd is a bit of a problem here as we are forced to walk the 
  514.           list again - even if the removed link was not the last one. Not nice... "
  515.         (links isNil) ifTrue:  [ 
  516.             listEnd <- nil
  517.         ]
  518.         ifFalse: [ 
  519.             l <- links.
  520.             [ l notNil ] whileTrue: [
  521.                 listEnd <- l.
  522.                 l <- l next
  523.             ]
  524.         ]
  525. |
  526.     size
  527.         (links isNil)
  528.             ifTrue: [ ^ 0 ]
  529.             ifFalse: [ ^ links size ]
  530. ]
  531. Methods Set 'all'
  532.     add: value
  533.         (self includes: value)
  534.             ifFalse: [ self addFirst: value ]
  535. ]
  536. Methods String 'all'
  537.     , value
  538.         (value isMemberOf: String)
  539.             ifTrue: [ (self size + value size) > 2000
  540.                     ifTrue: [ 'string too large' print. ^ self ]
  541.                     ifFalse: [ ^ <24 self value> ] ]
  542.             ifFalse: [ ^ self , value asString ]
  543. |
  544.     = value
  545.         (value isKindOf: String)
  546.             ifTrue: [ ^ super = value ]
  547.             ifFalse: [ ^ false ]
  548. |
  549.     < value
  550.         (value isKindOf: String)
  551.             ifTrue: [ ^ super < value ]
  552.             ifFalse: [ ^ false ]
  553. |
  554.     asByteArray    | newArray i |
  555.         newArray <- ByteArray new size: self size.
  556.         i <- 0.
  557.         self do: [:x | i <- i + 1. newArray at: i put: x asInteger].
  558.         ^ newArray
  559. |
  560.     asInteger
  561.         ^ self inject: 0 into: [:x :y | x * 10 + y digitValue ]
  562. |
  563.     basicAt: index
  564.         ^  (super basicAt: index) asCharacter
  565. |
  566.     basicAt: index put: aValue
  567.         (aValue isMemberOf: Char)
  568.             ifTrue: [ super basicAt: index put: aValue asInteger ]
  569.             ifFalse: [ smalltalk error:
  570.                 'cannot put non Char into string' ]
  571. |
  572.     asSymbol
  573.         ^ <83 self>
  574. |
  575.     copy
  576.         " catenation makes copy automatically "
  577.         ^ '',self
  578. |
  579.     copyFrom: position1 to: position2
  580.         ^ <33 self position1 position2>
  581. |
  582.     hash
  583.         ^ <82 self>
  584. |
  585.     printString
  586.         ^ '''' , self, ''''
  587. |
  588.     size
  589.         ^ <81 self>
  590. |
  591.     words: aBlock    | text index list |
  592.         list <- List new.
  593.         text <- self.
  594.         [ text <- text copyFrom: 
  595.             (text indexOf: aBlock ifAbsent: [ text size + 1])
  596.                 to: text size.
  597.           text size > 0 ] whileTrue:
  598.             [ index <- text 
  599.                 indexOf: [:x | (aBlock value: x) not ]
  600.                 ifAbsent: [ text size + 1].
  601.               list addLast: (text copyFrom: 1 to: index - 1).
  602.               text <- text copyFrom: index to: text size ].
  603.         ^ list asArray
  604. |
  605.     value
  606.         " evaluate self as an expression "
  607.         ^ ( '^ [ ', self, ' ] value' ) execute
  608. |
  609.     execute    | meth |
  610.         " execute self as body of a method "
  611.         meth <- Method new; text: 'compile ', self.
  612.         (meth compileWithClass: Object)
  613.             ifTrue: [ ^ meth executeWith: #(0) ].
  614.         ^ nil
  615. |
  616.     unixCommand
  617.         ^ <88 self>
  618. ]
  619.  
  620.